// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#include <sstream>
#include <string>

#include <nebula/core/config.h>

// Include various "api.h" entrypoints and check they don't leak internal symbols

#include <nebula/core/api.h>          // IWYU pragma: keep
#include <nebula/compute/api.h>  // IWYU pragma: keep
#include <nebula/io/api.h>       // IWYU pragma: keep
#include <nebula/ipc/api.h>      // IWYU pragma: keep

#include <nebula/csv/api.h>  // IWYU pragma: keep


#include <nebula/json/api.h>  // IWYU pragma: keep

#include <kmock/kmock-matchers.h>
#include <ktest/ktest.h>

#include <nebula/testing/ktest_util.h>
#include <nebula/testing/util.h>

namespace nebula {
/*
TEST(InternalHeaders, DCheckExposed) {
#ifdef DKCHECK
  FAIL() << "DKCHECK should not be visible from Nebula public headers.";
#endif
}
*/
TEST(InternalDependencies, OpenTelemetryExposed) {
#ifdef OPENTELEMETRY_VERSION
  FAIL() << "OpenTelemetry should not be visible from Nebula public headers.";
#endif
}

TEST(InternalDependencies, KSimdExposed) {
#ifdef KSIMD_VERSION_MAJOR
  FAIL() << "ksimd should not be visible from Nebula public headers.";
#endif
}

TEST(InternalDependencies, DateLibraryExposed) {
#ifdef HAS_CHRONO_ROUNDING
  FAIL() << "nebula::vendored::date should not be visible from Nebula public headers.";
#endif
}

TEST(InternalDependencies, ProtobufExposed) {
#ifdef PROTOBUF_EXPORT
  FAIL() << "Protocol Buffers should not be visible from Nebula public headers.";
#endif
}

TEST(TransitiveDependencies, WindowsHeadersExposed) {
#if defined(SendMessage) || defined(GetObject) || defined(ERROR_INVALID_HANDLE) || \
    defined(FILE_SHARE_READ) || defined(WAIT_TIMEOUT)
  FAIL() << "Windows.h should not be included by Nebula public headers";
#endif
}
/*
TEST(Misc, BuildInfo) {
  const auto& info = GetBuildInfo();
  // The runtime version (GetBuildInfo) should have the same major number as the
  // build-time version (NEBULA_VERSION), but may have a greater minor / patch number.
  ASSERT_EQ(info.version_major, NEBULA_VERSION_MAJOR);
  ASSERT_GE(info.version_minor, NEBULA_VERSION_MINOR);
  ASSERT_GE(info.version_patch, NEBULA_VERSION_PATCH);
  ASSERT_GE(info.version, NEBULA_VERSION);
  ASSERT_LT(info.version, NEBULA_VERSION + 1000 * 1000);  // Same major version
  std::stringstream ss;
  ss << info.version_major << "." << info.version_minor << "." << info.version_patch;
  ASSERT_THAT(info.version_string, ::testing::HasSubstr(ss.str()));
  ASSERT_THAT(info.full_so_version, ::testing::HasSubstr(info.so_version));
}

TEST(Misc, SetTimezoneConfig) {
#ifndef _WIN32
  KTEST_SKIP() << "Can only set the Timezone database on Windows";
#elif !defined(NEBULA_FILESYSTEM)
  KTEST_SKIP() << "Need filesystem support to test timezone config.";
#else
  auto fs = std::make_shared<nebula::fs::LocalFileSystem>();

  std::optional<std::string> tzdata_result = GetTestTimezoneDatabaseRoot();
  std::string tzdata_dir;
  if (tzdata_result.has_value()) {
    tzdata_dir = tzdata_result.value();
  } else {
    auto home_raw = std::getenv("USERPROFILE");
    std::string home = home_raw == nullptr ? "~" : std::string(home_raw);
    ASSERT_OK_AND_ASSIGN(tzdata_dir, fs->NormalizePath(home + "\\Downloads\\tzdata"));
  }
  ASSERT_OK_AND_ASSIGN(tzdata_dir, fs->NormalizePath(tzdata_dir));
  ASSERT_OK_AND_ASSIGN(auto tzdata_path,
                       nebula::internal::PlatformFilename::from_string(tzdata_dir));

  if (!nebula::internal::FileExists(tzdata_path).value_or(false)) {
    KTEST_SKIP() << "Couldn't find timezone database in expected dir: " << tzdata_dir;
  }
  // create a tmp directory
  ASSERT_OK_AND_ASSIGN(auto tempdir, nebula::internal::TemporaryDir::create("tzdata"));

  // Validate that setting tzdb to that dir fails
  nebula::GlobalOptions options = {std::make_optional(tempdir->path().to_string())};
  ASSERT_NOT_OK(nebula::Initialize(options));

  // Copy tzdb data from ~/Downloads
  auto selector = nebula::fs::FileSelector();
  selector.base_dir = tzdata_dir;
  selector.recursive = true;
  ASSERT_OK(nebula::fs::CopyFiles(fs, selector, fs, tempdir->path().to_string()));

  // Validate that tzdb is working
  ASSERT_OK(nebula::Initialize(options));
#endif
}
*/
}  // namespace nebula
